﻿using SFML.Audio;

namespace WolfCarol.SFU
{
    public class AudioSource : Entity
    {
        private Music? _music;

        private Sound? _sound;

        private bool _isMusicOrSound;

        public bool IsLoop
        {
            get
            {
                if (_isMusicOrSound)
                {
                    return _music != null ? _music.Loop : false;
                }
                else
                {
                    return _sound != null ? _sound.Loop : false;
                }
            }
            set
            {
                if (_isMusicOrSound)
                {
                    if (_music != null)
                    {
                        _music.Loop = value;
                    }
                }
                else
                {
                    if (_sound != null)
                    {
                        _sound.Loop = value;
                    }
                }
            }
        }

        public float Volume
        {
            get
            {
                if (_isMusicOrSound)
                {
                    return _music != null ? _music.Volume / 100f : 0f;
                }
                else
                {
                    return _sound != null ? _sound.Volume / 100f : 0f;
                }
            }
            set
            {
                float volume = Mathf.Clamp(value, 0f, 1f);
                volume *= 100f;
                if (_isMusicOrSound)
                {
                    if (_music != null)
                    {
                        _music.Volume = value;
                    }
                }
                else
                {
                    if (_sound != null)
                    {
                        _sound.Volume = value;
                    }
                }
            }
        }

        public bool IsPlaying
        {
            get
            {
                if (_isMusicOrSound)
                {
                    return _music != null ? _music.Status == SoundStatus.Playing : false;
                }
                else
                {
                    return _sound != null ? _sound.Status == SoundStatus.Playing : false;
                }
            }
        }

        public float Pitch
        {
            get
            {
                if (_isMusicOrSound)
                {
                    return _music != null ? _music.Pitch : 0f;
                }
                else
                {
                    return _sound != null ? _sound.Pitch : 0f;
                }
            }
            set
            {
                if (_isMusicOrSound)
                {
                    if (_music != null)
                    {
                        _music.Pitch = value;
                    }
                }
                else
                {
                    if (_sound != null)
                    {
                        _sound.Pitch = value;
                    }
                }
            }
        }

        public float Length
        {
            get
            {
                if (_isMusicOrSound)
                {
                    return _music != null ? _music.Duration.AsSeconds() : 0f;
                }
                else
                {
                    if (_sound != null && _sound.SoundBuffer != null)
                    {
                        return _sound.SoundBuffer.Duration.AsSeconds();
                    }
                    else
                    {
                        return 0f;
                    }
                }
            }
        }

        public float Time
        {
            get
            {
                if (_isMusicOrSound)
                {
                    return _music != null ? _music.PlayingOffset.AsSeconds() : 0f;
                }
                else
                {
                    return _sound != null ? _sound.PlayingOffset.AsSeconds() : 0f;
                }
            }
            set
            {
                if (_isMusicOrSound)
                {
                    if (_music != null)
                    {
                        _music.PlayingOffset = SFML.System.Time.FromSeconds(value);
                    }
                }
                else
                {
                    if (_sound != null)
                    {
                        _sound.PlayingOffset = SFML.System.Time.FromSeconds(value);
                    }
                }
            }
        }

        public SoundBuffer? Clip
        {
            get
            {
                if (_isMusicOrSound == false)
                {
                    return _sound?.SoundBuffer;
                }
                else
                {
                    return null;
                }
            }
            set
            {
                if (_isMusicOrSound == false && _sound != null)
                {
                    _sound.SoundBuffer = value;
                }
            }
        }

        public AudioSource(string fileName)
        {
            _music = new Music(fileName);
            _sound = new Sound();
            _isMusicOrSound = true;
        }

        public AudioSource(SoundBuffer buffer)
        {
            _sound = new Sound(buffer);
            _isMusicOrSound = false;
        }

        public static void PlayOnce(SoundBuffer buffer, float volume = 1f, float pitch = 1f)
        {
            Sound sound = new Sound(buffer);
            sound.Volume = Mathf.Clamp(volume, 0f, 1f) * 100f;
            sound.Pitch = pitch;
            sound.Play();
        }

        public void Play()
        {
            if (_isMusicOrSound)
            {
                _music?.Play();
            }
            else
            {
                _sound?.Play();
            }
        }

        public void Stop()
        {
            if (_isMusicOrSound)
            {
                _music?.Stop();
            }
            else
            {
                _sound?.Stop();
            }
        }

        public void Pause()
        {
            if (_isMusicOrSound)
            {
                _music?.Pause();
            }
            else
            {
                _sound?.Pause();
            }
        }
    }
}
